package processes;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;

import application.Application;

/**
 * It's a class where is possible to store information about processes. 
 * @author Miroslav Vozabal
 *
 */
public class ProcessDescriptor {
	private int id;
	private ProcessDescriptor consument;
	private Boolean canRead;
	private PipedInputStream in;
	private PipedOutputStream out;
	private ProcessDescriptor sibling;
	private ProcessDescriptor parent;
	private ArrayList<ProcessDescriptor> children;
	private String applicationName;
	private String workingDirectory;
	private Application thread;
	private static int processCounter = 0;
	private Boolean end;
	
	/**
	 * The Constructor.
	 * @param in
	 * @param out
	 * @param applicationName
	 * @param workingDirectory
	 * @param thread
	 */
	public ProcessDescriptor(PipedInputStream in,
			PipedOutputStream out, String aplicationName, String workingDirectory,
			Application thread) {
		this.in = in;
		this.out = out;
		this.applicationName = aplicationName;
		this.workingDirectory = workingDirectory;
		this.thread = thread;
		this.children = null;
		this.id = processCounter;
		processCounter++;
		this.canRead = false;
		this.end = false;
	}
	
	/**
	 * Gets the consumer.
	 * @return
	 */
	public ProcessDescriptor getConsument() {
		return consument;
	}

	/**
	 * Sets the consumer.
	 * @param consument
	 */
	public void setConsument(ProcessDescriptor consument) {
		this.consument = consument;
	}

	
	/**
	 * Gets the option of reading.
	 * @return
	 */
	public Boolean getCanRead() {
		return canRead;
	}

	/**
	 * Sets the option of reading.
	 * @param canRead
	 */
	public void setCanRead(Boolean canRead) {
		this.canRead = canRead;
	}

	/**
	 * Gets the end.
	 * @return
	 */
	public Boolean getEnd() {
		return end;
	}

	/**
	 * Sets the end.
	 * @param end
	 */
	public void setEnd(Boolean end) {
		this.end = end;
	}

	/**
	 * Connects piped streams.
	 * @throws IOException
	 */
	public void connect() throws IOException{
		in.connect(out);
	}
	
	
	/**
	 * Gets the PipedInputStream.
	 * @return
	 */
	public PipedInputStream getIn() {
		return in;
	}

	/**
	 * Sets the PipedInputStream.
	 * @param in
	 */
	public void setIn(PipedInputStream in) {
		this.in = in;
	}

	/**
	 * Gets the PipedOutputStream.
	 * @return
	 */
	public PipedOutputStream getOut() {
		return out;
	}

	/**
	 * Sets the PipedOutputStream.
	 * @param out
	 */
	public void setOut(PipedOutputStream out) {
		this.out = out;
	}

	/**
	 * Gets the sibling of the process.
	 * @return
	 */
	public ProcessDescriptor getSibling() {
		return sibling;
	}

	/**
	 * Sets the sibling of the process.
	 * @param sibling
	 */
	public void setSibling(ProcessDescriptor sibling) {
		this.sibling = sibling;
	}

	/**
	 * Gets the parent of the process.
	 * @return
	 */
	public ProcessDescriptor getParent() {
		return parent;
	}

	/**
	 * Sets the parent of the process.
	 * @param parent
	 */
	public void setParent(ProcessDescriptor parent) {
		this.parent = parent;
	}


	/**
	 * Gets the applicationName of the process.
	 * @return
	 */
	public String getApplicationName() {
		return applicationName;
	}

	/**
	 * Sets the application name of the process.
	 * @param aplicationName
	 */
	public void setAplicationName(String aplicationName) {
		this.applicationName = aplicationName;
	}

	/**
	 * Gets the working directory of the process.
	 * @return
	 */
	public String getWorkingDirectory() {
		return workingDirectory;
	}

	/**
	 * Sets the working directory of the process.
	 * @param workingDirectory
	 */
	public void setWorkingDirectory(String workingDirectory) {
		this.workingDirectory = workingDirectory;
	}

	/**
	 * Gets the thread of the process.
	 * @return
	 */
	public Application getThread() {
		return thread;
	}

	/**
	 * Sets the thread of the process.
	 * @param thread
	 */
	public void setThread(Application thread) {
		this.thread = thread;
	}

	/**
	 * Returns the id of the process.
	 * @return
	 */
	public int getId() {
		return id;
	}
	
	/**
	 * Sets the id of the process.
	 */
	public void setId(int id) {
		this.id = id;
	}
	
	/**
	 * Returns the children list.
	 * @return
	 */
	public ArrayList<ProcessDescriptor> getChildren() {
		return children;
	}
	
	/**
	 * Adds child to the children list. 
	 * @param processDescriptor
	 */
	public void addChild(ProcessDescriptor processDescriptor) {
		if (children == null) {
			children = new ArrayList<ProcessDescriptor>();
		}
		children.add(processDescriptor);
	}

	/**
	 * Sets the list of children.
	 * @param children
	 */
	public void setChildren(ArrayList<ProcessDescriptor> children) {
		this.children = children;
	}
	/**
	 * Returns the child at the specific index.
	 * @param index
	 * @return
	 */
	public ProcessDescriptor getChild(int index) {
		return children.get(index);
	}
		
	/**
	 * Deletes the child from list with value of processDescriptor.
	 * @param processDescriptor 
	 */
	public void cleanChild(ProcessDescriptor processDescriptor) {
		ArrayList<ProcessDescriptor> newChilren = new ArrayList<ProcessDescriptor>();
		for (ProcessDescriptor item : children) {
			if (processDescriptor.getId() != item.getId()) {
				newChilren.add(item);
			}
		}
		children = newChilren;
		if (children.isEmpty() == true) {
			children = null;
		}
	}

}